package 编程模式;

public class ThreadLocalValue {

    public static void main(String[] args) {
        Thread t1 = new MyThread("t1");
        Thread t2 = new MyThread("t2");
        t1.start();
        t2.start();
    }

    /**
     * 创建线程的几种方法：
     *      1. 继承 thread 类，实现 run 方法即可；
     *      2. 实现 runnable 接口，实现 run 方法，然后 new thread() 时添加此接口的实现类作为构造器参数
     *      3. 实现 callable 接口，实现
     */
    static class MyThread extends Thread {
        /**
         * ThreadLocal是Java提供给线程的，主要是解决线程没有私有变量而产生的；那具体怎么是怎么实现的呢？
         * 在 thread 类中，有一个thread local map变量，其是一个map结构，key是各个线程的 thread local对象，value 是通过 set()方法设置的值
         * 其中key是弱引用，value是强引用，在GC的时候，会回收key，而不会回收value上的强引用，所以会造成内存泄漏问题；如何解决这个问题呢?
         * java 已经替我们想好了，在调用 thread local 的remove，set，get 方法的时候会自动清理这些 key 为 null 的 thread local 变量值；
         * 不过还是建议手动调用 remove 来清理这些 key 为 null 的空引用；
         *
         * ----
         *
         * 强引用： 利用 new 关键字来调用， GC 不会清理这些被引用的对象；
         * 弱引用： 利用 WeakReference 类来创建，记录一些可有可无的对象，在守护线程进行 GC 时，不管 weak reference 是否有引用对象，都会清理；
         * 软引用： 利用 soft reference 类来创建，记录一些可有可无的对象，在守护线程进行 GC 时，如果内存足够，则不清理；如果内存不足，则清理；
         * 虚引用： 利用 Phantom Reference 类来创建，记录根本无用的对象，主要时记录被 GC 时回收的对象；此引用并不能调用对象实体中的方法；而且GC的时候，只要发现就清除；
         *
         */
        ThreadLocal threadLocal = new ThreadLocal();

        public MyThread(String name){
            super(name);
        }

        @Override
        public void run() {
            String s = Math.random() * 1000 + "=====";
            System.out.println(s + getName());
            threadLocal.set(s);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(getName() +"========"+ threadLocal.get());
        }
    }
}
